package org.xbrlapi.data.bdbxml.examples.dimensions;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Set;

import org.xbrlapi.Fact;
import org.xbrlapi.Instance;
import org.xbrlapi.aspects.AspectValue;
import org.xbrlapi.aspects.FactSet;
import org.xbrlapi.aspects.FactSetImpl;
import org.xbrlapi.data.Store;
import org.xbrlapi.data.bdbxml.examples.utilities.BaseUtilityExample;
import org.xbrlapi.loader.Loader;
import org.xbrlapi.sax.EntityResolver;
import org.xbrlapi.sax.EntityResolverImpl;
import org.xbrlapi.utilities.XBRLException;
import org.xbrlapi.xdt.ExplicitDimension;
import org.xbrlapi.xdt.ExplicitDimensionImpl;
import org.xbrlapi.xdt.LoaderImpl;
import org.xbrlapi.xdt.aspects.DimensionalAspectModel;
import org.xbrlapi.xdt.aspects.DimensionalAspectModelWithStoreCachingLabellers;
import org.xbrlapi.xdt.aspects.ExplicitDimensionAspectValue;
import org.xbrlapi.xlink.XLinkProcessor;
import org.xbrlapi.xlink.XLinkProcessorImpl;
import org.xbrlapi.xlink.handler.XBRLCustomLinkRecogniserImpl;
import org.xbrlapi.xlink.handler.XBRLXLinkHandlerImpl;

/**
 * Lists all documents in the data store. Additional commandline arguments
 * (optional ones marked with an *)
 * <ul>
 * <li>There are no additional commandline arguments for this utility.</li>
 * </ul>
 * These are in addition to those commandline arguments documented at
 *
 * @author Matt DeAngelis (ronin78 at gmail dot com)
 * @link BaseUtilityExample
 */
public class DimensionExample extends BaseUtilityExample {

    public DimensionExample(String[] args) throws XBRLException,
            URISyntaxException {
        URI targetURI = new URI("http://www.sec.gov/Archives/edgar/data/36047/000003604712000016/clgx-20111231.xml");
        boolean discoverXDT = true;

        argumentDocumentation = addArgumentDocumentation();
        parseArguments(args);
        String message = setUp();

        if (message.equals("")) {
            try {
                if (!discoverXDT) {
                    //Use default loader from Base Utility Example
                    System.out.println("Discovering with the default loader...\n");
                    loader.discover(targetURI);
                } else {
                    //Use XBRL-aware Loader to get Explicit Dimension Aspects
                    //I have marked the necessary import statement to use this Loader.  See also the getLoader() function at the top of the class.
                    System.out.println("Discovering with the default loader...\n");
                    Loader xdtLoader = getLoader(store);
                    xdtLoader.discover(targetURI);
                }

                System.out.println("Getting instance...\n");
                List<Instance> instances = store.getFragmentsFromDocument(
                        targetURI, "Instance");
                if (instances.size() > 1)
                    throw new XBRLException(
                            "There are duplicates of the target instance in the data store.  The store appears to be corrupted.");
                if (instances.size() == 0)
                    throw new XBRLException("The target document, " + targetURI
                            + ",is not an XBRL instance.");
                Instance instance = instances.get(0);

                //Number of Explicit Dimensions will be zero using the default Loader implementation
                System.out.println("Number of Explicit Dimensions in Store: " + store.<ExplicitDimension>getXMLResources(ExplicitDimensionImpl.class).size() + "\n");

                //Build and initialize Aspect Model and FactSet
                System.out.println("Preparing Aspect Model and FactSet...\n");
                DimensionalAspectModel aspectModel = new DimensionalAspectModelWithStoreCachingLabellers(store);
                aspectModel.initialise();
                FactSet factSet = new FactSetImpl(aspectModel);

                //Add a tractable subset of facts to the FactSet
                List<Fact> revfacts = instance.getFacts("http://fasb.org/us-gaap/2011-01-31", "SalesRevenueServicesNet");
                factSet.addFacts(revfacts);

                //Get all aspect values from FactSet and print characteristics.  The if statement is only triggered using the XDT-aware Loader implementation.
                int avcount = 0;
                for (AspectValue av : factSet.getAspectValues()) {
                    avcount++;
                    System.out.println("Printing Aspect Value #" + avcount);
                    System.out.println("Aspect: " + av.getAspectId());
                    System.out.println("Class: " + av.getClass().getName());
                    System.out.println("AspectValue: " + av.getId());
                    if (av.getClass().getName().contentEquals("org.xbrlapi.xdt.aspects.ExplicitDimensionAspectValue")) {
                        ExplicitDimensionAspectValue edav = (ExplicitDimensionAspectValue) av;
                        System.out.println("This Aspect Value belongs to an Explicit Dimension.");
                        System.out.println("Aspect ID: " + edav.getAspectId() + " and ID: " + edav.getId() + " and localname: " + edav.getLocalname() + " and namespace: " + edav.getNamespace());
                    }
                    Set<Fact> facts = factSet.getFacts(av);
                    System.out.println("Number of facts with this value: " + facts.size() + "\n");
                }

            } catch (Exception e) {
                badUsage(e.getMessage());
            }

        } else {
            badUsage(message);
        }

        tearDown();
    }

    /**
     * @param args The array of commandline arguments.
     * @throws URISyntaxException
     * @throws XBRLException
     */
    public static void main(String[] args) throws XBRLException,
            URISyntaxException {
        @SuppressWarnings("unused")
        DimensionExample utility = new DimensionExample(args);
    }

    private Loader getLoader(Store store) throws XBRLException {
        XBRLXLinkHandlerImpl xlinkHandler = new XBRLXLinkHandlerImpl();
        XBRLCustomLinkRecogniserImpl clr = new XBRLCustomLinkRecogniserImpl();
        XLinkProcessor xlinkProcessor = new XLinkProcessorImpl(xlinkHandler, clr);

        EntityResolver entityResolver = new EntityResolverImpl(cache);
        Loader myLoader = new LoaderImpl(store, xlinkProcessor, entityResolver);
        myLoader.setCache(cache);
        myLoader.setEntityResolver(entityResolver);
        xlinkHandler.setLoader(myLoader);
        return myLoader;
    }

}
